package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.tbit.uqbike.constant.BrandRemoteConfigConstant;
import com.tbit.uqbike.constant.RedisConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.AccountUserBound;
import com.tbit.uqbike.object.pojo.BrandRemoteConfig;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.business.AccountUserFreeLoginService;
import com.tbit.uqbike.webmanager.controller.interceptor.HttpHeadName;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import com.tbit.uqbike.webmanager.dao.core.AccountUserDao;
import com.tbit.uqbike.webmanager.dao.core.BrandRemoteConfigDao;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @AUTHOR: wei.xing
 * @DATE: 2023-05-15 17:18
 **/
@Service
public class AccountFreeLoginServiceImpl implements AccountUserFreeLoginService {

    @Autowired
    private AccountUserDao accountUserDao;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisService redisService;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private BrandRemoteConfigDao brandRemoteConfigDao;

    @Override
    public void freeLogin(Integer accountUserId, Integer accountId) {

        //是否刷新token
        if (isRefreshToken(accountId)) {
            BrandRemoteConfig brandRemoteConfig = getBrandRemoteConfig(accountUserId);
            if (brandRemoteConfig != null) {
                Date tokenExpireDate = getTokenExpireDate(accountUserId, brandRemoteConfig);
                int seconds = (int) DateUtil.between(new Date(), tokenExpireDate, DateUnit.SECOND, false);
                if (seconds <= 0) {
                    LoginInfo loginInfo = tokenService.getLoginInfo();
                    tokenService.destroyToken(loginInfo);
                    throw new BaseException(SystemCodeEnum.TOKEN_EXPIRE);
                }
                //token续期
                tokenService.refreshToken(seconds);
                refreshLoginDate(accountUserId, seconds, getLastLoginDate(accountUserId));
            }
        }
    }

    @Override
    public void resetFreeLogin(Integer accountId) {
        //Pipeline批量删除
        redisService.delByPrefixPipeline(RedisConstant.ACCOUNT_USER_PC_FREE_LOGIN + accountId);
        redisService.delByPrefixPipeline(RedisConstant.ACCOUNT_USER_MAIN_FREE_LOGIN + accountId);
    }

    @Override
    public void refreshLoginDate(Integer accountUserId, Integer second, Date date) {
        String loginDateKey = RedisConstant.ACCOUNT_USER_PC_LOGIN_DATE + accountUserId;
        redisService.add(loginDateKey, JSON.toJSONString(date), second);
    }


    private BrandRemoteConfig getBrandRemoteConfig(Integer accountUserId) {
        AccountUserBound accountUserBound = accountUserDao.getBoundByUserId(accountUserId);
        Integer brandId = accountUserBound.getAccountId();
        Account account = accountDao.getByAccountId(brandId);
        if (account.getType().equals(2)) {
            brandId = account.getParentId();
        } else if (account.getType().equals(3)) {
            brandId = accountDao.getByAccountId(account.getParentId()).getParentId();
        }
        return brandRemoteConfigDao.getBrandRemoteConfig(brandId, BrandRemoteConfigConstant.PC_FREE_LOGIN);
    }

    private Date getTokenExpireDate(Integer accountUserId, BrandRemoteConfig brandRemoteConfig) {
        //账号免登录配置
        String[] strings = brandRemoteConfig.getParamKV().split("&");
        String freeLoginMode = strings[0].substring(strings[0].indexOf("=") + 1);
        int effectiveMinute = Integer.parseInt(strings[1].substring(strings[1].indexOf("=") + 1));

        Date tokenExpireDate;
        if ("0".equals(freeLoginMode)) {
            //根据最近请求时间
            tokenExpireDate = DateUtil.offsetMinute(new Date(), effectiveMinute);
        } else {
            //根据最近登录时间
            Date lastLoginDate = getLastLoginDate(accountUserId);
            if (lastLoginDate == null) {
                throw new BaseException(SystemCodeEnum.TOKEN_EXPIRE);
            }
            tokenExpireDate = DateUtil.offsetMinute(lastLoginDate, effectiveMinute);
        }
        return tokenExpireDate;
    }

    private boolean isRefreshToken(Integer accountId) {
        HttpServletRequest request = ServletUtils.getRequest();
        String token = request.getHeader(HttpHeadName.REQUEST_ATTR_NAME_TOKEN);
        if (null == token) {
            token = request.getParameter(HttpHeadName.REQUEST_ATTR_NAME_TOKEN);
        }

        String freeLoginKey = RedisConstant.ACCOUNT_USER_PC_FREE_LOGIN + accountId + ":" + token;
        if (!redisService.hasKey(freeLoginKey)) {
            redisService.add(freeLoginKey, "", 3600);
            return true;
        }
        return false;
    }

    private Date getLastLoginDate(Integer accountUserId) {
        String loginDateKey = RedisConstant.ACCOUNT_USER_PC_LOGIN_DATE + accountUserId;
        String loginDateStr = redisService.get(loginDateKey);
        if (loginDateStr == null) {
            return null;
        }
        return JSON.parseObject(loginDateStr, Date.class);
    }

}
